package process

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"learningProject/shangguigu/client/utils"
	message "learningProject/shangguigu/common" // 引包引到文件夹一级即可
	"net"
	"os"
)

type UserProcess struct {
}

// 注册函数
func (this *UserProcess) Register(userId int, userPwd string, userName string) (err error) {
	//连接服务器
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err =", err)
		return
	}
	// 延时关闭
	defer conn.Close()

	// 连接成功，发送消息给服务器
	var mes message.Message
	mes.Type = message.RegisterMegType
	// 创建一个LoginMes结构体
	var registerMeg message.RegisterMeg
	registerMeg.User.UserId = userId
	registerMeg.User.UserPwd = userPwd
	registerMeg.User.UserName = userName

	// 将registerMeg序列化，然后放入mes的Data
	data, err := json.Marshal(registerMeg)
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	mes.Data = string(data) // data是byte切片,要转成string

	// 将mes序列化
	data, err = json.Marshal(mes) // 这里的data就是要发送的数据
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	tf := &utils.Transfer{
		Conn: conn,
	}
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("注册发送信息错误", err)
	}

	mes, err = tf.ReadPkg() // mes是registerResMeg
	if err != nil {
		fmt.Println("读取服务器返回的信息失败")
		return
	}

	// 反序列化成RegisterResMeg
	var registerResMes message.RegisterResMeg
	err = json.Unmarshal([]byte(mes.Data), &registerResMes) //mes.Data是string类型，要强转
	if err != nil {
		fmt.Println("json.Unmarshal mes.Data err")
		return
	}

	if registerResMes.Code == 200 { // 登陆成功
		fmt.Println("注册成功，重新登录")
	} else {
		fmt.Println(registerResMes.Error)
	}
	os.Exit(0) // 注册完就退出
	return
}

// 写一个登录函数
func (this *UserProcess) Login(userId int, userPwd string) (err error) {
	//连接服务器
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err =", err)
		return
	}
	// 延时关闭
	defer conn.Close()

	// 连接成功，发送消息给服务器
	var mes message.Message
	mes.Type = message.LoginMesType
	// 创建一个LoginMes结构体
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd

	// 将loginMes序列化，然后放入mes的Data
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	mes.Data = string(data) // data是byte切片,要转成string

	// 将mes序列化
	data, err = json.Marshal(mes) // 这里的data就是要发送的数据
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	//发送data的长度和内容给服务器
	//注意  conn.Write必须传入byte切片
	var pkgLen uint32
	pkgLen = uint32(len(data))
	var buf [4]byte                              // uint32是4个字节，所以这里是[4]byte
	binary.BigEndian.PutUint32(buf[0:4], pkgLen) //将pkgLen转为byte切片
	// 发送长度
	n, err := conn.Write(buf[:4]) //n表示发送了几字节的数据
	if n != 4 || err != nil {
		fmt.Println("conn.Write(buf) err", err)
		return
	}
	fmt.Printf("客户端成功发送数据长度=%d\n", len(data))

	// 发送消息本身
	_, err = conn.Write(data) //n表示发送了几字节的数据
	if err != nil {
		fmt.Println("conn.Write(data) err", err)
		return
	}
	fmt.Printf("客户端成功发送数据本身\n")

	// 处理服务器返回的消息
	tf := &utils.Transfer{
		Conn: conn, // 将UserProcess结构体的Conn赋给utils包下的Transfer结构体
	}
	mes, err = tf.ReadPkg()
	if err != nil {
		fmt.Println("读取服务器返回的信息失败")
		return
	}
	// 反序列化成LoginResMes
	var loginResMes message.LoginResMeg
	err = json.Unmarshal([]byte(mes.Data), &loginResMes) //mes.Data是string类型，要强转
	if err != nil {
		fmt.Println("json.Unmarshal mes.Data err")
		return
	}

	if loginResMes.Code == 200 { // 登陆成功
		// 初始化CurUser
		CurUser.Conn = conn
		CurUser.UserId = userId
		CurUser.UserStatus = message.UserOnline

		// 显示当前在线用户列表
		fmt.Println("当前在线用户")
		for _, v := range loginResMes.UserIds {
			// 如果不想显示自己
			if v == userId {
				continue
			}
			fmt.Println("用户id:\t", v)
			// 完成客户端map的初始化
			// 创建User
			user := &message.User{
				UserId:     v,
				UserStatus: message.UserOnline, // 默认上线
			}
			onlineUsers[v] = user
		}
		fmt.Print("\n\n")

		// *********这里还要起一个协程，保持与服务端的通信************
		// 如果服务器有数据推送给客户端，可以接受并显示
		go ServerProcessMes(conn)

		// 循环显示登陆成功的界面
		for {
			ShowMenu()
		}
	} else {
		fmt.Println(loginResMes.Error)
	}

	// 处理服务器
	return
}
